home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / portfoli / bootst11.lzh / PF BOOTSTRAP VATIPX PREMCAPC < prev    next >
Text File  |  1989-05-28  |  9KB  |  414 lines

  1. /*
  2.  * Copyright (c) 1983 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)remcap.c    5.2 (Berkeley) 9/2/88";
  20. #endif /* not lint */
  21.  
  22. /*
  23.  * remcap - routines for dealing with the remote host data base
  24.  *
  25.  * derived from termcap
  26.  */
  27. #include <sys/file.h>
  28. #include <ctype.h>
  29.  
  30. #ifndef BUFSIZ
  31. #define    BUFSIZ        1024
  32. #endif
  33. #define MAXHOP        32        /* max number of tc= indirections */
  34. #define SYSREMOTE    "/etc/remote"    /* system remote file */
  35.  
  36. #define    tgetent        rgetent
  37. #define    tnchktc        rnchktc
  38. #define    tnamatch    rnamatch
  39. #define    tgetnum        rgetnum
  40. #define    tgetflag    rgetflag
  41. #define    tgetstr        rgetstr
  42. #define    E_TERMCAP    RM = SYSREMOTE
  43. #define V_TERMCAP    "REMOTE"
  44. #define V_TERM        "HOST"
  45.  
  46. char    *RM;
  47.  
  48. /*
  49.  * termcap - routines for dealing with the terminal capability data base
  50.  *
  51.  * BUG:        Should use a "last" pointer in tbuf, so that searching
  52.  *        for capabilities alphabetically would not be a n**2/2
  53.  *        process when large numbers of capabilities are given.
  54.  * Note:    If we add a last pointer now we will screw up the
  55.  *        tc capability. We really should compile termcap.
  56.  *
  57.  * Essentially all the work here is scanning and decoding escapes
  58.  * in string capabilities.  We don't use stdio because the editor
  59.  * doesn't, and because living w/o it is not hard.
  60.  */
  61.  
  62. static    char *tbuf;
  63. static    int hopcount;    /* detect infinite loops in termcap, init 0 */
  64. char    *tskip();
  65. char    *tgetstr();
  66. char    *tdecode();
  67. char    *getenv();
  68. static    char *remotefile;
  69.  
  70. /*
  71.  * Get an entry for terminal name in buffer bp,
  72.  * from the termcap file.  Parse is very rudimentary;
  73.  * we just notice escaped newlines.
  74.  */
  75. tgetent(bp, name)
  76.     char *bp, *name;
  77. {
  78.     char lbuf[BUFSIZ], *cp, *p;
  79.     int rc1, rc2;
  80.  
  81.     remotefile = cp = getenv(V_TERMCAP);
  82.     if (cp == (char *)0 || strcmp(cp, SYSREMOTE) == 0) {
  83.         remotefile = cp = SYSREMOTE;
  84.         return (getent(bp, name, cp));
  85.     } else {
  86.         if ((rc1 = getent(bp, name, cp)) != 1)
  87.             *bp = '\0';
  88.         remotefile = cp = SYSREMOTE;
  89.         rc2 = getent(lbuf, name, cp);
  90.         if (rc1 != 1 && rc2 != 1)
  91.             return (rc2);
  92.         if (rc2 == 1) {
  93.             p = lbuf;
  94.             if (rc1 == 1)
  95.                 while (*p++ != ':')
  96.                     ;
  97.             if (strlen(bp) + strlen(p) > BUFSIZ) {
  98.                 write(2, "Remcap entry too long\n", 23);
  99.                 return (-1);
  100.             }
  101.             strcat(bp, p);
  102.         }
  103.         tbuf = bp;
  104.         return (1);
  105.     }
  106. }
  107.  
  108. getent(bp, name, cp)
  109.     char *bp, *name, *cp;
  110. {
  111.     register int c;
  112.     register int i = 0, cnt = 0;
  113.     char ibuf[BUFSIZ], *cp2;
  114.     int tf;
  115.  
  116.     tbuf = bp;
  117.     tf = 0;
  118.     /*
  119.      * TERMCAP can have one of two things in it. It can be the
  120.      * name of a file to use instead of /etc/termcap. In this
  121.      * case it better start with a "/". Or it can be an entry to
  122.      * use so we don't have to read the file. In this case it
  123.      * has to already have the newlines crunched out.
  124.      */
  125.     if (cp && *cp) {
  126.         if (*cp!='/') {
  127.             cp2 = getenv(V_TERM);
  128.             if (cp2 == (char *)0 || strcmp(name,cp2) == 0) {
  129.                 strcpy(bp,cp);
  130.                 return (tnchktc());
  131.             } else
  132.                 tf = open(E_TERMCAP, O_RDONLY);
  133.         } else
  134.             tf = open(RM = cp, O_RDONLY);
  135.     }
  136.     if (tf == 0)
  137.         tf = open(E_TERMCAP, O_RDONLY);
  138.     if (tf < 0)
  139.         return (-1);
  140.     for (;;) {
  141.         cp = bp;
  142.         for (;;) {
  143.             if (i == cnt) {
  144.                 cnt = read(tf, ibuf, BUFSIZ);
  145.                 if (cnt <= 0) {
  146.                     close(tf);
  147.                     return (0);
  148.                 }
  149.                 i = 0;
  150.             }
  151.             c = ibuf[i++];
  152.             if (c == '\n') {
  153.                 if (cp > bp && cp[-1] == '\\') {
  154.                     cp--;
  155.                     continue;
  156.                 }
  157.                 break;
  158.             }
  159.             if (cp >= bp+BUFSIZ) {
  160.                 write(2,"Remcap entry too long\n", 23);
  161.                 break;
  162.             } else
  163.                 *cp++ = c;
  164.         }
  165.         *cp = 0;
  166.  
  167.         /*
  168.          * The real work for the match.
  169.          */
  170.         if (tnamatch(name)) {
  171.             close(tf);
  172.             return (tnchktc());
  173.         }
  174.     }
  175. }
  176.  
  177. /*
  178.  * tnchktc: check the last entry, see if it's tc=xxx. If so,
  179.  * recursively find xxx and append that entry (minus the names)
  180.  * to take the place of the tc=xxx entry. This allows termcap
  181.  * entries to say "like an HP2621 but doesn't turn on the labels".
  182.  * Note that this works because of the left to right scan.
  183.  */
  184. tnchktc()
  185. {
  186.     register char *p, *q;
  187.     char tcname[16];    /* name of similar terminal */
  188.     char tcbuf[BUFSIZ];
  189.     char *holdtbuf = tbuf;
  190.     int l;
  191.  
  192.     p = tbuf + strlen(tbuf) - 2;    /* before the last colon */
  193.     while (*--p != ':')
  194.         if (p<tbuf) {
  195.             write(2, "Bad remcap entry\n", 18);
  196.             return (0);
  197.         }
  198.     p++;
  199.     /* p now points to beginning of last field */
  200.     if (p[0] != 't' || p[1] != 'c')
  201.         return (1);
  202.     strcpy(tcname, p+3);
  203.     q = tcname;
  204.     while (*q && *q != ':')
  205.         q++;
  206.     *q = 0;
  207.     if (++hopcount > MAXHOP) {
  208.         write(2, "Infinite tc= loop\n", 18);
  209.         return (0);
  210.     }
  211.     if (getent(tcbuf, tcname, remotefile) != 1) {
  212.         if (strcmp(remotefile, SYSREMOTE) == 0)
  213.             return (0);
  214.         else if (getent(tcbuf, tcname, SYSREMOTE) != 1)
  215.             return (0);
  216.     }
  217.     for (q = tcbuf; *q++ != ':'; )
  218.         ;
  219.     l = p - holdtbuf + strlen(q);
  220.     if (l > BUFSIZ) {
  221.         write(2, "Remcap entry too long\n", 23);
  222.         q[BUFSIZ - (p-holdtbuf)] = 0;
  223.     }
  224.     strcpy(p, q);
  225.     tbuf = holdtbuf;
  226.     return (1);
  227. }
  228.  
  229. /*
  230.  * Tnamatch deals with name matching.  The first field of the termcap
  231.  * entry is a sequence of names separated by |'s, so we compare
  232.  * against each such name.  The normal : terminator after the last
  233.  * name (before the first field) stops us.
  234.  */
  235. tnamatch(np)
  236.     char *np;
  237. {
  238.     register char *Np, *Bp;
  239.  
  240.     Bp = tbuf;
  241.     if (*Bp == '#')
  242.         return (0);
  243.     for (;;) {
  244.         for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
  245.             continue;
  246.         if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
  247.             return (1);
  248.         while (*Bp && *Bp != ':' && *Bp != '|')
  249.             Bp++;
  250.         if (*Bp == 0 || *Bp == ':')
  251.             return (0);
  252.         Bp++;
  253.     }
  254. }
  255.  
  256. /*
  257.  * Skip to the next field.  Notice that this is very dumb, not
  258.  * knowing about \: escapes or any such.  If necessary, :'s can be put
  259.  * into the termcap file in octal.
  260.  */
  261. static char *
  262. tskip(bp)
  263.     register char *bp;
  264. {
  265.  
  266.     while (*bp && *bp != ':')
  267.         bp++;
  268.     if (*bp == ':')
  269.         bp++;
  270.     return (bp);
  271. }
  272.  
  273. /*
  274.  * Return the (numeric) option id.
  275.  * Numeric options look like
  276.  *    li#80
  277.  * i.e. the option string is separated from the numeric value by
  278.  * a # character.  If the option is not found we return -1.
  279.  * Note that we handle octal numbers beginning with 0.
  280.  */
  281. tgetnum(id)
  282.     char *id;
  283. {
  284.     register int i, base;
  285.     register char *bp = tbuf;
  286.  
  287.     for (;;) {
  288.         bp = tskip(bp);
  289.         if (*bp == 0)
  290.             return (-1);
  291.         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
  292.             continue;
  293.         if (*bp == '@')
  294.             return (-1);
  295.         if (*bp != '#')
  296.             continue;
  297.         bp++;
  298.         base = 10;
  299.         if (*bp == '0')
  300.             base = 8;
  301.         i = 0;
  302.         while (isdigit(*bp))
  303.             i *= base, i += *bp++ - '0';
  304.         return (i);
  305.     }
  306. }
  307.  
  308. /*
  309.  * Handle a flag option.
  310.  * Flag options are given "naked", i.e. followed by a : or the end
  311.  * of the buffer.  Return 1 if we find the option, or 0 if it is
  312.  * not given.
  313.  */
  314. tgetflag(id)
  315.     char *id;
  316. {
  317.     register char *bp = tbuf;
  318.  
  319.     for (;;) {
  320.         bp = tskip(bp);
  321.         if (!*bp)
  322.             return (0);
  323.         if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
  324.             if (!*bp || *bp == ':')
  325.                 return (1);
  326.             else if (*bp == '@')
  327.                 return (0);
  328.         }
  329.     }
  330. }
  331.  
  332. /*
  333.  * Get a string valued option.
  334.  * These are given as
  335.  *    cl=^Z
  336.  * Much decoding is done on the strings, and the strings are
  337.  * placed in area, which is a ref parameter which is updated.
  338.  * No checking on area overflow.
  339.  */
  340. char *
  341. tgetstr(id, area)
  342.     char *id, **area;
  343. {
  344.     register char *bp = tbuf;
  345.  
  346.     for (;;) {
  347.         bp = tskip(bp);
  348.         if (!*bp)
  349.             return (0);
  350.         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
  351.             continue;
  352.         if (*bp == '@')
  353.             return (0);
  354.         if (*bp != '=')
  355.             continue;
  356.         bp++;
  357.         return (tdecode(bp, area));
  358.     }
  359. }
  360.  
  361. /*
  362.  * Tdecode does the grung work to decode the
  363.  * string capability escapes.
  364.  */
  365. static char *
  366. tdecode(str, area)
  367.     register char *str;
  368.     char **area;
  369. {
  370.     register char *cp;
  371.     register int c;
  372.     register char *dp;
  373.     int i;
  374.  
  375.     cp = *area;
  376.     while ((c = *str++) && c != ':') {
  377.         switch (c) {
  378.  
  379.         case '^':
  380.             c = *str++ & 037;
  381.             break;
  382.  
  383.         case '\\':
  384.             dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
  385.             c = *str++;
  386. nextc:
  387.             if (*dp++ == c) {
  388.                 c = *dp++;
  389.                 break;
  390.             }
  391.             dp++;
  392.             if (*dp)
  393.                 goto nextc;
  394.             if (isdigit(c)) {
  395.                 c -= '0', i = 2;
  396.                 do
  397.                     c <<= 3, c |= *str++ - '0';
  398.                 while (--i && isdigit(*str));
  399.                 break;
  400.               }
  401.             /* \x where x is not understood is passed as \x */
  402.             /* to allow the handshake routine to do further */
  403.             /* escape processing.                */
  404.             *cp++ = '\\';
  405.             break;
  406.         }
  407.         *cp++ = c;
  408.     }
  409.     *cp++ = 0;
  410.     str = *area;
  411.     *area = cp;
  412.     return (str);
  413. }
  414.